<template>
    <div>
        <FilterPanel ref="filterPanelRef" @filterVideoList="filterVideoList" />
        <vue-scroll
            :ops="ops"
            :style="contentSize"
            @mousedown.native="mouseDown"
            @mousemove.native="mouseMove"
            @mouseup.native="mouseUp"
            @mouseleave.native="mouseLeave"
            id="vueScroll"
            @handle-resize="setCoversAround"
            @handle-scroll="handleScroll"
        >
            <a-spin :spinning="spinning">
                <a-row type="flex" justify="space-around" class="video-row" v-for="(row, key) in rowList" :key="key">
                    <a-col
                        :draggable="false"
                        v-for="(v, k) in row"
                        :key="k"
                        @contextmenu="handleContextmenu(coverIndex(key, row, k))"
                        :style="`opacity: ${JSON.stringify(v) !== '{}' ? 100 : 0};`"
                    >
                        <div
                            :class="
                                `cover-wrap ${
                                    selectedCovers.findIndex((v) => v == coverIndex(key, row, k)) > -1
                                        ? 'selected'
                                        : 'normal'
                                }`
                            "
                        >
                            <img
                                :id="`cover${k}`"
                                :src="v.imgSrc ? v.imgSrc : ''"
                                :width="coverWidth"
                                height="215"
                                class="video-cover"
                            />
                            <div class="title">
                                <span class="name">{{ v.newName ? v.newName : v.name }}</span>
                                <span class="score">{{ v.score }}</span>
                            </div>
                        </div>
                    </a-col>
                </a-row>
            </a-spin>
            <div ref="selectedAreaRef" v-show="!spinning" class="selected-area" />
        </vue-scroll>
        <DirModal ref="dirModalRef" />
    </div>
</template>
<script>
    import { readData, delData } from '@/util/file-action'
    import { showRightMenu } from '@/util/right-menu/index'
    import { getMenuItem } from '@/util/right-menu/video-menu'
    import FilterPanel from '@/components/filter-panel/index.vue'
    import DirModal from '@/components/dir-modal/index.vue'
    import { remote, ipcRenderer } from 'electron'

    let mouseDown = null // 鼠标按下事件
    let selectedArea = null
    let vueScroll = null
    let keyDown = ''
    let scrollTop = 0 // 滚动垂直距离

    export default {
        name: 'VideoHall',
        components: {
            FilterPanel,
            DirModal,
        },
        data() {
            return {
                videoList: [],
                tags: [],
                checkTags: [],
                newName: '',
                curKey: null,
                ops: {
                    vuescroll: {},
                    scrollPanel: { scrollingX: false, easing: 'easeInQuad' },
                    rail: {},
                    bar: { background: '#E8E8E8' },
                },
                contentSize: 'height: 100%',
                coverWidth: 150,
                contentWidth: 0,
                rowList: [],
                rowNum: 1, // 一行展示的封面数
                spinning: false,
                selectedCovers: [], // 选中的视频封面
                videoWin: null,
            }
        },
        watch: {
            checkTags: {
                handler(nval) {
                    let name = ''
                    nval.forEach((v, k) => {
                        if (v) {
                            name += this.tags[k].w
                        }
                    })
                    this.newName = name
                },
                deep: true,
            },
            contentWidth(nval) {
                let n = 1
                while (this.coverWidth * n + n * 16 < nval) {
                    n++
                }
                n = n - 1 > 0 ? n - 1 : 1
                if (n !== this.rowNum) {
                    this.setRowList(n, this.videoList)
                    this.rowNum = n
                }
                this.$nextTick(() => {
                    this.setCoversAround('contentWidth')
                })
            },
            '$store.state.videos.videoList': {
                async handler(nval) {
                    for (const i in nval) {
                        this.$set(this.videoList, i, nval[i])
                    }
                },
                deep: true,
                immediate: true,
            },
            '$store.state.videos.spinning': {
                handler(nval) {
                    this.spinning = nval
                },
            },
        },
        async mounted() {
            this.$nextTick(() => {
                this.listenSize()
            })

            selectedArea = this.$refs.selectedAreaRef
            vueScroll = document.getElementById('vueScroll')

            document.addEventListener('keydown', (e) => {
                keyDown = e.key
            })
            document.addEventListener('keyup', (e) => {
                keyDown = ''
            })
        },
        methods: {
            handleScroll(vertical, horizontal, nativeEvent) {
                scrollTop = vertical.scrollTop
                this.setCoversAround('handleScrll')
            },
            coverIndex(key, row, k) {
                return key * row.length + k
            },
            pauseEvent(e) {
                if (e.stopPropagation) e.stopPropagation()
                if (e.preventDefault) e.preventDefault()
                e.cancelBubble = true
                e.returnValue = false
                return false
            },
            /**
             * 记录每个封面的上下左右的位置
             * @param {string} who 调用者
             */
            setCoversAround(who) {
                // console.log(who)
                const videoRows = document.getElementsByClassName('video-row')
                if (videoRows) {
                    let coversAround = []
                    videoRows.forEach((row) => {
                        row.childNodes.forEach((el) => {
                            if (el.style.opacity == '100') {
                                const { left, top, width, height } = el.getBoundingClientRect()
                                coversAround.push({
                                    left,
                                    top,
                                    right: left + width,
                                    bottom: top + height,
                                })
                            }
                        })
                    })
                    sessionStorage.setItem('coversAround', JSON.stringify(coversAround))
                }
            },
            mouseDown(e) {
                this.pauseEvent(e)
                mouseDown = e
                const { clientX, clientY } = e

                if (keyDown != 'Control') {
                    this.selectedCovers = []
                }
                let coversAround = sessionStorage.getItem('coversAround')
                coversAround = JSON.parse(coversAround)
                coversAround.forEach(({ left, right, top, bottom }, k) => {
                    if (clientX > left && clientX < right && clientY > top && clientY < bottom) {
                        this.selectedCovers.push(k)
                    }
                })
            },
            /**
             * 拖拽选中封面
             */
            isSelectCovers() {
                const { left, top, width, height } = selectedArea.getBoundingClientRect()
                this.selectedCovers = []
                let coversAround = sessionStorage.getItem('coversAround')
                coversAround = JSON.parse(coversAround)
                coversAround.forEach((v, k) => {
                    // 选择区域的左边小于封面的右边，选择区域的右边小于封面的左边
                    if (left < v.right && left + width > v.left && top < v.bottom && top + height > v.top) {
                        this.selectedCovers.push(k)
                    }
                })
            },
            mouseMove(e) {
                this.pauseEvent(e)
                // 按下鼠标左键
                if (mouseDown && e.buttons == 1) {
                    const { left: gl, top: gt } = vueScroll.getBoundingClientRect()
                    let width = 0
                    let left = 0
                    let top = 0
                    let height = 0
                    // 不能使用offsetX，数据会漂移
                    if (e.clientX < mouseDown.clientX) {
                        // 左移
                        left = e.clientX - gl
                        width = mouseDown.clientX - e.clientX
                    } else {
                        // 右移
                        left = mouseDown.clientX - gl
                        width = e.clientX - mouseDown.clientX
                    }
                    if (e.clientY < mouseDown.clientY) {
                        // 上移
                        top = e.clientY - gt + scrollTop
                        height = mouseDown.clientY - e.clientY
                    } else {
                        // 下移
                        top = mouseDown.clientY - gt + scrollTop
                        height = e.clientY - mouseDown.clientY
                    }
                    selectedArea.style.left = left + 'px'
                    selectedArea.style.top = top + 'px'
                    selectedArea.style.width = width + 'px'
                    selectedArea.style.height = height + 'px'
                    this.isSelectCovers()
                }
            },
            mouseUp(e) {
                this.pauseEvent(e)
                selectedArea.style.width = '0px'
                selectedArea.style.height = '0px'
                selectedArea.style.top = '0px'
                selectedArea.style.left = '0px'
                mouseDown = null
            },
            mouseLeave(e) {
                this.mouseUp(e)
            },
            listenSize() {
                const resizeObserver = new ResizeObserver((entries) => {
                    const filterHeight = this.$refs.filterPanelRef?.$el.getBoundingClientRect().height ?? 0
                    const { height, width } = entries[0].contentRect
                    this.contentSize = `height: ${Math.floor(height - filterHeight - 10)}px`
                    this.contentWidth = Math.floor(width) - 48
                })
                resizeObserver.observe(document.querySelector('.ant-layout-content'))
            },
            setRowList(n, list) {
                this.rowList = []
                let row = []
                let rowList = []
                for (let i = 0; i < list.length; i += n) {
                    for (let x = i; x < i + n; x++) {
                        row.push(list[x] ?? {})
                    }
                    rowList.push(row)
                    row = []
                }
                for (let i = 0; i < rowList.length; i++) {
                    this.$set(this.rowList, i, rowList[i])
                }
            },
            filterVideoList(arr) {
                let list = this.videoList
                if (!arr.find((v) => v == '全部')) {
                    list = []
                    this.videoList.forEach((item) => {
                        let times = 0
                        for (const v of arr) {
                            if (item.category.find((cate) => cate == v)) times++
                            if (times == arr.length) {
                                list.push(item)
                            }
                        }
                    })
                }
                this.setRowList(this.rowNum, list)
            },
            handleContextmenu(k) {
                showRightMenu(getMenuItem(this.videoList[k], k, this.menuFunc))
            },
            /**
             * 点击菜单选项后执行的方法
             * @param {Object} data
             * @param {string} k
             * @param {string} type
             */
            menuFunc(data, k, type) {
                let func = () => {}
                if (type == 'moreInfo') {
                    func = () => {
                        this.$router.push(`/editVideo?k=${k}`)
                    }
                } else if (type == 'delete') {
                    delData([data.id], k, 'video')
                    const fileData = readData('video')
                    this.$store.dispatch('videos/setVideoList', fileData.videos)
                } else if (type == 'play') {
                    this.videoWin = new remote.BrowserWindow({
                        width: 800,
                        height: 600,
                        webPreferences: {
                            nodeIntegration: true, // 是否集成 Nodejs
                            contextIsolation: false,
                            enableRemoteModule: true,
                            nodeIntegrationInWorker: true, // 开启多线程
                        },
                    })
                    let windowsHref = window.location.href
                    const locationURL = windowsHref.substring(0, windowsHref.indexOf('#') + 1)
                    const _data = JSON.stringify(data)
                    this.videoWin.loadURL(locationURL + `/videoPlayer?video=${_data}`)
                    this.videoWin.on('close', (e) => {
                        this.videoWin = null
                        ipcRenderer.send('ffmpegServer')
                    })
                }
                func()
            },
        },
    }
</script>
<style lang="less" scoped>
    @coverwidth: 140px;
    .video-row {
        height: 100%;
        user-select: none;
        .cover-wrap {
            padding: 8px;
            border-radius: 3px;
            margin-bottom: 5px;
            .video-cover {
                border-radius: 5px;
            }
            .panel {
                width: @coverwidth;
                height: 215px;
                border-radius: 5px;
                border: 2px solid #cccccc;
                .open-btn {
                    height: 100px;
                }
                .plus {
                    font-size: 30px;
                    color: #cccccc;
                }
            }
            .title {
                width: 100%;
                text-align: center;
                max-width: @coverwidth;
                margin-top: 5px;
                .name {
                    color: #1890ff;
                    margin-right: 5px;
                }
                .score {
                    color: #e09015;
                }
            }
        }
        .selected {
            background: #cce8ff;
            border: 1px solid #92c7f3;
        }
        .normal {
            background: white;
            border: 1px solid white;
        }
    }
    .selected-area {
        background: #92c7f3;
        border: 1px solid #499bdd;
        opacity: 0.5;
        position: absolute;
    }
</style>
